
#ifndef __GSL_EXT_FUNCTION_H__

#include <gsl_ext/gsl_ext_multimin.h>

#include <gsl/gsl_multimin.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef enum
{
  GSL_EXT_FUN_EVAL_SYM,
  GSL_EXT_FUN_EVAL_PRECOMP
}
gsl_ext_func_eval_type;

typedef enum
{
  GSL_EXT_DERIV_EVAL_SYM,
  GSL_EXT_DERIV_EVAL_FD
}
gsl_ext_deriv_eval_type;

gsl_multimin_function *
gsl_ext_multimin_function_alloc(char *expr,
                                gsl_ext_func_eval_type fe,
                                void *params);
void 
gsl_ext_multimin_function_free(gsl_multimin_function *f);

gsl_multimin_function_fdf *
gsl_ext_multimin_function_fdf_alloc(char *expr,
                                    gsl_ext_func_eval_type fe,
                                    gsl_ext_deriv_eval_type ge,
                                    void *params);
void 
gsl_ext_multimin_function_fdf_free(gsl_multimin_function_fdf *f);

gsl_ext_multimin_function_fd2f *
gsl_ext_multimin_function_fd2f_alloc(char *expr, 
                                   gsl_ext_func_eval_type fe, 
                                   gsl_ext_deriv_eval_type ge, 
                                   gsl_ext_deriv_eval_type he, 
                                   void *params);
void 
gsl_ext_multimin_function_fd2f_free(gsl_ext_multimin_function_fd2f *f);

typedef struct
{
  double (*f)(const gsl_vector *x, void *params);
  void (*df)(const gsl_vector *x, void *params, gsl_vector *df);
  void (*d2f)(const gsl_vector *x, void *params, gsl_matrix *d2f);
  gsl_ext_func_eval_type f_eval_type;
  gsl_ext_deriv_eval_type df_eval_type;
  gsl_ext_deriv_eval_type d2f_eval_type;
  void *f_evaluator;
  void *df_evaluator;
  void *d2f_evaluator;
  void *params;
  unsigned int f_eval_counter;
  unsigned int df_eval_counter;
  unsigned int d2f_eval_counter;
}
gsl_ext_multimin_function_params;

void 
gsl_ext_multimin_fdf(const gsl_vector *x,
                     void *params,
                     double *f,
                     gsl_vector *g);

void 
gsl_ext_multimin_fd2f(const gsl_vector *x,
                      void *params,
                      double *f,
                      gsl_vector *g,
                      gsl_matrix *H);

#ifdef __cplusplus
}
#endif

#define __GSL_EXT_FUNCTION_H__

#endif
